package com.gitee.l0km.aocache;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.ConstructorSignature;
import org.aspectj.lang.reflect.MethodSignature;

import com.gitee.l0km.aocache.ContextHolder.AocacheContext;
import com.gitee.l0km.aocache.annotations.AoCacheable;
import com.gitee.l0km.aocache.annotations.AoClear;
import com.gitee.l0km.aocache.annotations.AoClears;
import com.gitee.l0km.aocache.annotations.AoUpdateable;
import com.gitee.l0km.aocache.config.AoCacheGlobalConfig;
import com.gitee.l0km.aocache.config.CacheConfig;
import com.gitee.l0km.aocache.config.CacheConfigSupplier;
import com.gitee.l0km.aocache.config.CacheConfigSuppliers;
import com.gitee.l0km.aocache.config.JoinPointConfigLoader;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.FluentIterable;
import com.google.common.primitives.Primitives;

import static com.google.common.base.Preconditions.checkNotNull;
/**
 * 管理类成员(方法,构造方法/字段)对应结果缓存映射对象的缓存实现<br>
 * aocache为每个类成员定义一个独立的缓存对象{@link InvokeCache}。
 * 每个成员的缓存数据保存在一个{@link InvokeCache}实例中
 * <p>
 * <b>主要功能：</b>
 * <ul>
 *   <li>为每个类成员方法或构造方法提供独立的缓存管理</li>
 *   <li>支持通过注解配置缓存行为</li>
 *   <li>提供调试日志输出功能</li>
 *   <li>支持从配置文件加载切入点配置</li>
 * </ul>
 * @author guyadong
 * @see InvokeCache
 * @see AoCacheable
 * @see AoClear
 * @see AoClears
 */
public class MemberCache 
	implements ThrowingFunction<MemberKey, InvokeCache,Throwable>,AocacheConstant{
	public static final MemberCache INSTANCE = new MemberCache(ThrowingFunctionCached.builder());
	private final StaticMemberCache staticMemberCache;
	private final NonStaticMemberCache nonStaticMemberCache;
	/**
	 * 是否输出调试信息
	 */
	private boolean debugOutput;
	/**
	 * 是否输出详细调试信息
	 */
	private boolean debugOutputDetail;
	private boolean override;
	private boolean outputAroundCost;
	private AocacheLogger logger = AocacheLogger.MUTE;
	/**
	 * 是否使用加载的切入点配置。
	 * 当该字段为true时，会从切入点配置文件中获取缓存配置；
	 * 为false时，则不使用切入点配置文件中的配置。
	 */
	private final boolean usingLoadedJoinPoints;

	/**
	 * 运行时缓存配置供应商，用于存储和管理成员的运行时缓存配置。
	 * <p>
	 * 使用{@link RuntimeCacheConfigSupplier}实现，它提供了线程安全的并发映射来存储配置信息。
	 * 该配置对象允许在运行时动态地为不同的成员（如方法、构造函数）设置缓存配置。
	 * <p>
	 * 例如，可以通过调用{@link #setCacheConfig(Member, Object, CacheConfig)}方法为特定的成员设置缓存配置。
	 * 这些配置将影响该成员在缓存操作中的行为，如缓存的有效期、大小限制等。
	 * <p>
	 * 注意：对运行时配置的更改会立即生效，并且会清除与指定成员相关的所有缓存数据，以确保新的配置在下一次方法调用时生效。
	 */
	private final RuntimeCacheConfigSupplier runtimeCacheConfig = new RuntimeCacheConfigSupplier();
	
	/**
	 * 构造函数，初始化MemberCache实例<br>
	 * 初始化逻辑：<br>
	 * 1. 从AoCacheGlobalConfig获取默认配置初始化debugOutput、debugOutputDetail等字段<br>
	 * 2. 当debugOutput为true时，将logger设置为AocacheLogger.DEFAULT开启日志输出<br>
	 * 3. 设置usingLoadedJoinPoints标志位，决定是否使用加载的切入点配置<br>
	 * 
	 * @param builder 缓存构建器，用于配置缓存的基本参数如并发级别、初始容量等。
	 *                通过builder可以设置缓存的弱引用、软引用策略以及过期时间等特性。
	 * 
	 */
	@SuppressWarnings({ "rawtypes" })
	MemberCache(ThrowingFunctionCached.Builder builder) {
		this.staticMemberCache = new StaticMemberCache(builder);
		this.nonStaticMemberCache = new NonStaticMemberCache(builder);
		/** 使用AoCacheGlobalConfig提供的默认值初始化字段 */
		this.debugOutput = AoCacheGlobalConfig.debugOutput;
		this.debugOutputDetail = AoCacheGlobalConfig.debugOutputDetail;
		this.override = AoCacheGlobalConfig.override;
		this.outputAroundCost = AoCacheGlobalConfig.outputAroundCost;
		if (this.debugOutput) {
			this.logger = AocacheLogger.DEFAULT;
		}
		this.usingLoadedJoinPoints = AoCacheGlobalConfig.usingLoadedJoinPoints;
	}

	/**
	 * 设置指定成员在特定目标对象下的缓存配置。
	 * <p>
	 * 该方法为外部提供API方式为指定的类成员（如方法、构造函数）和目标对象设置缓存配置。<br>
	 * 配置信息将影响该成员在缓存操作中的行为，如缓存的有效期、大小限制等。<br>
	 * <p>
	 * 注意：该方法会清除与指定成员相关的所有缓存数据。<br>
	 * 新的配置会在下一次方法调用时生效<br>
	 * 建议：在初始化阶段调用该方法来动态调整缓存配置。<br>
	 * 
	 * @param member 要设置缓存配置的成员对象，如方法或构造函数。
	 * @param target 成员的调用对象,member为静态成员时忽略此参数<br>
	 *               <ul>
	 *               <li>member为非静态成员时，target 为成员的调用对象</li>
	 *               <li>为 null 则清除member的所有目标对象的缓存数据；</li>
	 *               </ul>
	 * @param config 要应用的缓存配置对象，包含了缓存的各种参数设置。
	 */
	public void setCacheConfig(Member member, Object target, CacheConfig config) {
		checkNotNull(member, "member can not be null");
		checkNotNull(config, "config can not be null");
		MemberKey memberKey = MemberKey.of(member, target);
		runtimeCacheConfig.put(member, target, config.rebuild());
		removeCache(memberKey);
	}

	/**
	 * 移除指定成员键对应的缓存。
	 * <p>
	 * 如果成员是非静态的，并且目标对象为null，则会移除该成员的所有目标对象的缓存。
	 * <p>
	 * 否则，仅移除指定成员键对应的缓存。
	 * 
	 * @param memberKey 要移除缓存的成员键对象。
	 */
	private void removeCache(MemberKey memberKey) {
		if (!Modifier.isStatic(memberKey.member.getModifiers()) && null == memberKey.target) {
			int removeCount = 0;
			TargetCache targetCache = nonStaticMemberCache.getValueOrNull(memberKey.member);
			if(null == targetCache) {
				return;
			}
			for (Object tgt : targetCache.cache.asMap().keySet().toArray(new Object[0])) {
				targetCache.remove(tgt);
				removeCount++;
			}
			if (debugOutput) {
				logger.log("\t└─REMOVE ALL CACHE({}) of Member:{}", removeCount, memberKey.member);
			}
		} else {
			if (debugOutput) {
				logger.log("REMOVE CACHE of {}", memberKey);
			}
			remove(memberKey);
		}
	}
	/**
	 * 指定日志输出对象，不为{@code null}开启调试信息输出，否则关闭调试信息输出
	 * @param logger 日志输出对象
	 * @param override 为{@code true}则 {@link InvokeCache} 使用 {@link #debugOutput}，忽略 {@link CacheConfig#debugOutput()}定义
	 * @param debugOutputDetail 是否输出详细调试信息
	 * @param outputAroundCost 是否输出切面调用耗时信息
	 */
	public void setLogger(AocacheLogger logger, boolean override, boolean debugOutputDetail, boolean outputAroundCost) {
		this.logger = MoreObjects.firstNonNull(logger, AocacheLogger.MUTE);
		this.debugOutput = (null != logger);
		this.override = override;
		this.debugOutputDetail = debugOutputDetail;
		this.outputAroundCost = outputAroundCost;
	}
	/**
	 * 获取当前调试输出状态
	 * 
	 * @return 如果调试输出已启用则返回true，否则返回false
	 */
	public boolean isDebugOutput() {
		return debugOutput;
	}
    /**
     * 获取当前详细调试输出状态
     * 
     * @return 如果详细调试输出已启用则返回true，否则返回false
     */
    public boolean isDebugOutputDetail() {
        return debugOutputDetail;
    }
    /**
     * 根据给定的MemberKey对象，计算并返回对应的InvokeCache实例。<p>
     * 此方法会按照以下优先级计算获取缓存配置：<br>
     * <li>从外部输入的缓存配置接口对象中获取配置。</li>
     * <li>从{@link #runtimeCacheConfig}中获取配置。</li>
     * <li>从外部切入点(JoinPoint)配置中获取配置。</li>
     * <li>从成员注解中获取配置。</li><p>
     * 如果获取到有效的缓存配置，则使用该配置构建并返回InvokeCache实例；
     * 若未找到有效的配置，则使用默认配置构建InvokeCache。
     *
     * @param input 包含成员信息和目标对象的MemberKey对象。
     * @return 基于配置创建的InvokeCache实例。
     * @throws Throwable 如果在计算或构建缓存过程中发生异常。
     */
	@Override
    public InvokeCache apply(MemberKey input) throws Throwable {
		CacheConfig config;
		if(null != input.inputSupplier) {
			config = input.inputSupplier.configOf(input.member, input.target);
			if(null!= config) {
				return buildCache(config, input.member, input.target);
			}
		}
		config = runtimeCacheConfig.configOf(input.member, input.target);
		if(null != config) {
			return buildCache(config, input.member, input.target);
		}

		if(null!= input.jpConfigSupplier) {
			config = input.jpConfigSupplier.configOf(input.member, input.target);
			if(null!= config) {
				return buildCache(config, input.member, input.target);
			}
		}
		/** 从注解中获取缓存配置 */
		AoCacheable annot = AocacheUtils.readAoCacheable((AnnotatedElement)input.member);
		if(annot == null ) {
			config= CacheConfig.DEFAULT_CONFIG;
		}else {
			config =  new CacheConfig(annot);
		}
		return buildCache(config, input.member, input.target);
	}

    /**
     * 根据缓存配置创建 {@link InvokeCache} 实例<p>
     * 该方法会根据传入的缓存配置对象 {@link CacheConfig} 和成员对象 {@link Member}，创建一个新的缓存实例。<p>
     * 具体步骤如下：<br>
     * <li>根据配置设置缓存的键值引用类型（弱引用、软引用）。</li>
     * <li>设置缓存的初始容量、并发级别、最大大小、最大权重等参数。</li>
     * <li>设置缓存的过期策略，包括写入后过期、访问后过期、写入后刷新等。</li>
     * <li>根据配置记录缓存统计信息。</li>
     * <li>设置参数包装器和返回值包装器。</li>
     * <li>最后，使用配置好的构建器创建并返回一个新的 {@link InvokeCache} 实例。</li>
     *
     * @param config 缓存配置对象，包含了缓存的各种参数设置。
     * @param member 要创建缓存的成员对象，如方法或构造函数。
     * @param target 用于解析类型的目标对象
     * @return 基于配置创建的 {@link InvokeCache} 实例。
     */
	private InvokeCache buildCache(CacheConfig config, Member member, Object target) {
		
		ThrowingFunctionCached.Builder<InvokeKey, Object> builder = ThrowingFunctionCached.builder(); 
		if(config.weakKeys()) {
			builder.weakKeys();
		}
		if(config.weakValues()) {
			builder.weakValues();
		}else if (config.softValues()) {
			builder.softValues();
		}
		if(config.initialCapacity()>=0) {
			builder.initialCapacity(config.initialCapacity());
		}
		if(config.concurrencyLevel()>0) {
			builder.concurrencyLevel(config.initialCapacity());
		}
		if(config.maximumSize()>=0) {
			builder.maximumSize(config.maximumSize());
		}
		if(config.maximumWeight()>=0) {
			builder.maximumWeight(config.maximumWeight());
		}
		if(config.expireAfterWrite()>=0) {
			builder.expireAfterWrite(config.expireAfterWrite(),config.expireAfterWriteTimeUnit());
		}
		if(config.expireAfterAccess()>=0) {
			builder.expireAfterAccess(config.expireAfterAccess(),config.expireAfterAccessTimeUnit());
		}
		if(config.refreshAfterWrite()>=0) {
			builder.refreshAfterWrite(config.refreshAfterWrite(),config.refreshAfterWriteTimeUnit());
		}
		if (config.removalListener() != null) {
			RemovalListener<InvokeKey, Object> rml = config.removalListener();
			builder.removalListener(rml);
		}
		if(AoCacheGlobalConfig.recordStats) {
			builder.recordStats();
		}
		
		Function<?, ?>[] argWrappers = SafeStrategy.CLONE.argWrappersOf(member, target, config.copyArgs());
		Function<?, ?>  returnWrapper = config.returnSafeStrategy().returnWrapperOf(member, target);
		Optional<Type> returnType;
		if (member instanceof Method) {
			Type resolveType = AocacheUtils.resolveType(target, ((Method) member).getGenericReturnType());
			returnType = Optional.of(resolveType);
		}else {
			returnType = Optional.absent();
		}
		return builder.build(InvokeCache.class, 
				override? debugOutput: config.debugOutput(),
				override? debugOutputDetail: config.debugOutputDetail(),
				override? outputAroundCost: config.outputAroundCost(),
				logger,
				argWrappers,
				returnWrapper,
				config.returnSafeStrategy(),
				returnType);
	}

	/** 
	 * 从{@link loadConfigs}
	 */
	/**
	 * @see #around(ProceedingJoinPoint, CacheConfigSupplier)
	 */
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		return around(joinPoint,null);
    }	

	/**
	 * [around]方法缓存读取切面执行
	 * @param joinPoint
	 * @param configGetter 缓存配置接口实现，为{@code null}则尝试从方法注解中获取配置
	 * @throws Throwable
	 */
	public Object around(ProceedingJoinPoint joinPoint, CacheConfigSupplier configGetter) throws Throwable {
		long startTime = System.nanoTime();
		InvokeCache invokeCache = null;
		InvokeKey invokeKey = null;
		try {
			Signature signature = joinPoint.getSignature();
			Member member;
			if(signature instanceof MethodSignature) {
				Method method = ((MethodSignature)signature).getMethod();
				if(Primitives.unwrap(method.getReturnType()).equals(void.class)) {
					/** void 类型不支持 */
					if(debugOutput) {
						logger.log("skip: {}",joinPoint.toLongString());
					}
					return joinPoint.proceed();
				}
				member = method;
			}else if(signature instanceof ConstructorSignature) {
				member = ((ConstructorSignature)signature).getConstructor();
			}else{
				/** 其他类型暂时不支持 */
				if(debugOutput) {
					logger.log("skip: {}",joinPoint.toLongString());
				}
				return joinPoint.proceed();
			}
			/** 从切入点配置文件获取缓存配置 */
			Object jpConfig = usingLoadedJoinPoints ? JoinPointConfigLoader.joinPointConfigOf(joinPoint.toLongString()) : null;
			invokeKey = new InvokeKey(joinPoint);
			if(Boolean.FALSE.equals(jpConfig)) {
				/** 禁用缓存 */
				if(debugOutput) {
					logger.log("JPC skip: {}",joinPoint.toLongString());
				}
				if (PerformanceProfiler.enableLog) {
					long proceedStartTime = System.nanoTime();
					try {
						return joinPoint.proceed();
					} finally {
						/** 计算proceed调用纯耗时 */
						invokeKey.proceedRealCost.set(System.nanoTime() - proceedStartTime);
					}
				}else {
					return joinPoint.proceed();
				}
			}else {
				MemberKey memberKey = MemberKey.of(member, joinPoint.getTarget(),
						CacheConfigSuppliers.of(member, joinPoint.getTarget(), jpConfig), 
						configGetter);
				return (invokeCache = get(memberKey)).get(invokeKey);
			}
		} finally {
			AocacheContext ctx = ContextHolder.CONTEXT.get();
			if (null != invokeKey) {
				long cost = System.nanoTime() - startTime;
				/** 不记录刷新调用 */
				if (PerformanceProfiler.enableLog && !ContextHolder.isRefreshInvocation(ctx)) {
					/** （持久化）记录around调用耗时 */
					PerformanceProfiler.addRecord(
							/** 切入点 */
							joinPoint, 
							/** 参数哈希 */
							Arrays.hashCode(invokeKey.args),
							/** 记录around调用次数，自动递增 */
							invokeKey.aroundCounter.incrementAndGet(), 
							/** around调用耗时(纳秒) */
							cost,
							/** 计算调用纯耗时(纳秒) */
							invokeKey.proceedRealCost.get(), 
							/** 当前时间 */
							new Date());
				}
				if(invokeCache != null && outputAroundCost(invokeCache)){
					/** 计算around调用耗时(毫秒) */
					float milliseconds = cost / 1000000F;
					String msg = String.format("\nAROUND COST: [%.4fms]\n\t└─%s\n\t\t└─InvokeKey:%s", 
							milliseconds, joinPoint.toString(), invokeKey.toSimpleString());
					logger.log(msg);
				}
			}
			/** 如果不是手动清除，则在方法调用结束自动清除上下文 */
			if(!ContextHolder.isManualClean(ctx)){
				ContextHolder.clearLocalContext();
			}
		}
	}
	/**
	 * 清除所有缓存项。<p>
	 * 此方法会调用 {@link ThrowingFunctionCached#cache} 的 {@code invalidateAll()} 方法，<br>
	 * 从而将缓存中的所有条目都标记为无效，达到清除缓存的目的。
	 */
	public void clear(){
		staticMemberCache.clear();
		nonStaticMemberCache.clear();
	}

    /**
     * 获取指定成员在给定目标对象下的缓存大小。<p>
     * 如果成员对象为 null，或者该成员没有对应的缓存，将返回 -1。<br>
     * 如果成员是非静态的，并且目标对象为 null，则会尝试查找该成员所有目标对象的缓存情况。<p>
     * 
     * @param member 要查询缓存大小的成员对象，如方法或构造函数。
     * @param target 成员的调用对象，当成员为静态成员时，该参数可忽略；<br>
     *               若成员为非静态成员，且该参数为 null，则会查找该成员所有目标对象的缓存情况。
     * @return 若存在对应的缓存，返回缓存的大小；否则返回 -1。
     */
    public long sizeOf(Member member, Object target) {
		if(null != member) {
			MemberKey memberKey = MemberKey.of(member, target);
			InvokeCache ic = getValueOrNull(memberKey);
			if(ic != null) {
				return ic.size();
			}
		}
		return -1L;
	}
	/**
	 * 清理指定{@link Member}对应的缓存清理操作，为{@code null}或不存在对应的缓存忽略。<p>
	 * 此方法用于清理指定成员的缓存。<br>
	 * 如果成员为非静态成员，且目标对象为null，则会清理所有目标对象的缓存。<br>
	 * 否则则仅清理该目标对象对应的缓存。<p>
	 * 
	 * @param member 要清理缓存的成员对象，如方法或构造函数。
	 * @param target Member为非静态成员时，target为成员的调用对象。
	 */
	public void cleanUp(Member member, Object target) {
		if(null != member) {
			if(!Modifier.isStatic(member.getModifiers()) && null == target) {
				/** 如果是非静态成员，且 target 为 null，即要求清除所有 target 的缓存 */
				int clearCount = 0;
				TargetCache targetCache = nonStaticMemberCache.getValueOrNull(member);
				if(null == targetCache) {
					return;
				}

				for(Object tgt : targetCache.cache.asMap().keySet().toArray(new Object[0])) {
					InvokeCache ic = targetCache.getValueOrNull(tgt);
					if(null != ic) {
						ic.cleanUp();
						clearCount++;
					}
				}
				if(debugOutput) {
					logger.log("\t└─CLEANUP ALL CACHE({}) of Member:{}", clearCount ,member);	
				}
			} else {
				MemberKey memberKey = MemberKey.of(member, target);
				InvokeCache ic = getValueOrNull(memberKey);
				if(ic != null) {
					ic.cleanUp();
				}
			}
		}
	}

	/**
     * 清除{@link Member}对应的缓存，为{@code null}或不存在对应的缓存忽略
     * <p>
     * 此方法用于清除指定成员的缓存。<br>
     * 如果成员为非静态成员，且目标对象为null，则会清除所有目标对象的缓存。<br>
     * 否则则仅清除该目标对象对应的缓存。
     * <p>
     * 
     * @param member 要清除缓存的成员对象，如方法或构造函数。
     * @param target Member为非静态成员时，target为成员的调用对象。
     */
    public void clear(Member member, Object target) {
		if(null != member) {
			if(!Modifier.isStatic(member.getModifiers()) && null == target) {
				/** 如果是非静态成员，且 target 为 null，即要求清除所有 target 的缓存 */
				int clearCount = 0;
				TargetCache targetCache = nonStaticMemberCache.getValueOrNull(member);
				if(null == targetCache) {
					return;
				}
				for(Object tgt : targetCache.cache.asMap().keySet().toArray(new Object[0])) {
					InvokeCache ic = targetCache.getValueOrNull(tgt);
					if(null != ic) {
						ic.clear();
						clearCount++;
					}
				}
				if(debugOutput) {
					logger.log("\t└─CLEAR ALL CACHE({}) of Member:{}", clearCount ,member);	
				}
			} else {
				MemberKey memberKey = MemberKey.of(member, target);
				InvokeCache ic = getValueOrNull(memberKey);
				if(ic != null) {
					ic.clear();
				}
			}
		}
	}
    /**
	 * 清除{@link Member}对应的缓存，为{@code null}或不存在对应的缓存忽略
	 * @param clazz
	 * @param methodName
	 * @param parameterTypes
	 * @param target 方法为非静态方法时，target为方法的调用对象
	 * @throws NoSuchMethodException
	 */
	private void clear(Class<?>clazz,String methodName, Class<?>[]parameterTypes, Object target) throws NoSuchMethodException {
		Member member = AocacheUtils.resolveAccessibleExecutableMember(clazz, methodName, parameterTypes, target, null);
		clear(member, target);
	}
	
	/**
	 * 根据切入点信息和清除缓存注解(@AoClear)数组，获取@AoClear注解对应的成员(方法/构造方法)的目标对象数组。<p>
	 * 规则如下：<br>
	 * <li>若切入点方法的参数数量等于注解数组的长度，则将参数作为目标对象数组。</li>
	 * <li>若切入点方法只有一个参数且该参数为对象数组，则将该数组作为目标对象数组。</li>
	 * <li>否则，将切入点的目标对象填充到与注解数组长度相同的数组中作为目标对象数组。</li>
	 * 
	 * @param joinPoint 切入点信息，包含被拦截方法的详细信息。
	 * @param annots 清除缓存注解数组，用于指定要清除缓存的目标方法或构造方法。
	 * @return 目标对象数组，用于确定要清除缓存的具体对象。
	 */
	private Object[] getTargets(JoinPoint joinPoint, AoClear[] annots) {
		Object[] targets = new Object[annots.length];
		Arrays.fill(targets, joinPoint.getTarget());
		Object[] args = joinPoint.getArgs();
		if (args.length == 1 && args[0] instanceof Object[]) {
			/** 
			 * 切入点方法只有一个参数且该参数为对象数组
			 * 将该数组作为目标对象数组
			 * 如果参数数组长度小于目标对象数组长度，则只复制前几个参数
			 */
			Object[] arg0 = (Object[]) args[0];
			System.arraycopy(arg0, 0, targets, 0, Math.min(arg0.length, targets.length));
		} else if (args.length == annots.length) {
			targets = args;
		}
		return targets;
	}

	/**
	 * [afterReturing]清除缓存切面执行<br>
	 * 拦截的方法返回类型为void则在方法正常执行后强制清除指定方法或构造方法的缓存，
	 * 拦截的方法返回类型为boolean则返回值{@code result}为{@code true}时才执行缓存清理
	 * @param joinPoint
	 * @param result 拦截方法的返回值
	 * @throws NoSuchMethodException 
	 */
	public void afterReturingClear(JoinPoint joinPoint, Object result) {
		Signature signature = joinPoint.getSignature();
		Method method;
		if(signature instanceof MethodSignature) {
			method = ((MethodSignature)signature).getMethod();
			Class<?> returnType = Primitives.unwrap(method.getReturnType());
			boolean force = !returnType.equals(boolean.class);
			/**
			 * 从拦截方法查找注解获取要清除缓存的目标方法或构造方法
			 */
			AoClear[] annots = aoClearsOf(method);
			if(annots.length>0) {
				/**
				 * 返回值类型非boolean或返回值为true时执行清除缓存操作
				 */
				if(force || Boolean.TRUE.equals(result)) {
					/**  
					 * 获取@AoClear注解对应的目标对象数组
					 */
					Object[] targets = getTargets(joinPoint, annots);
					for(int i = 0; i < annots.length; i++) {
						AoClear annot = annots[i];	
						Class<?> targetClass = annot.targetClass();
						/**
						 * 注解中没有指定targetClass则默认为拦截方法所属的类型
						 */
						if(targetClass.equals(Object.class)) {
							targetClass = method.getDeclaringClass();
						}
						try {
							clear(targetClass, annot.methodName(), annot.parameterTypes(), targets[i]);
						} catch (NoSuchMethodException e) {
							if(debugOutput) {
								logger.log(e);
							}
						}
					}
				}else if(Boolean.FALSE.equals(result)) {
					if(debugOutput) {
						logger.log("SKIP CLEAR Caused by return false");
					}
				}
			}
		}
    }	
    /**
     * [before]清除缓存切面执行<p>
     * 拦截的方法执行前清除指定方法的缓存<br>
     * 从拦截方法查找注解获取要清除缓存的目标方法或构造方法，根据注解配置清除对应缓存
     * 
     * @param joinPoint 切入点信息，包含被拦截方法的详细信息
     */
    public void beforeClear(JoinPoint joinPoint) {
		Signature signature = joinPoint.getSignature();
		if(signature instanceof MethodSignature) {
			Method method = ((MethodSignature)signature).getMethod();
			/**
			 * 从拦截方法查找注解获取要清除缓存的目标方法或构造方法
			 */
			AoClear annot = method.getAnnotation(AoClear.class);
			if(null != annot) {
				Class<?> targetClass = annot.targetClass();
				/**
				 * 注解中没有指定targetClass则默认为拦截方法所属的类型
				 */
				if(targetClass.equals(Object.class)) {
					targetClass = method.getDeclaringClass();
				}
				/** 获取目标对象,如果切入点方法定义了参数，则获取第一个参数作为目标对象 */
				Object target = joinPoint.getTarget();
				if(joinPoint.getArgs().length > 0){
					target = joinPoint.getArgs()[0];
				}
				try {
					clear(targetClass, annot.methodName(), annot.parameterTypes(), target);
				} catch (NoSuchMethodException e) {
					if(debugOutput) {
						logger.log(e);
					}
				}
			}
		}
	}
	/**
	 * 从拦截方法查找 {@link AoClear} 注解，没有找到返回空数组
	 * @param method
	 */
	private AoClear[] aoClearsOf(Method method) {
		AoClear annot = method.getAnnotation(AoClear.class);
		if(null != annot) {
			return new AoClear[] {annot};
		}
		AoClears annots = method.getAnnotation(AoClears.class);
		if(null != annots) {
			return FluentIterable.from(annots.value())
					.copyInto(new LinkedHashSet<>())
					.toArray(new AoClear[0]);
		}else {
			return new AoClear[0];
		}
	}
	
	/**
	 * 通过反射机制执行缓存方法并缓存结果
	 * <p>
	 * 主要功能：
	 * <ul>
	 *   <li>使用反射调用method.invoke()执行目标方法</li>
	 *   <li>自动处理反射调用产生的InvocationTargetException异常</li>
	 *   <li>将正常返回值和异常统一包装为缓存对象</li>
	 * </ul>
	 *
	 * @param method 要执行的目标方法对象，通过反射机制获取
	 * @param target 方法所属的目标对象实例，通常从切面JoinPoint中获取
	 * @param args 方法调用参数数组，保持与反射调用参数一致
	 * @return 经过{@link #asCached}包装的缓存对象，包含以下三种情况：
	 *         <ul>
	 *         <li>null</li>
	 *         <li>Throwable异常实例</li>
	 *         <li>普通值实例</li>
	 *         </ul>
	 */
	private Object reflectCompute(Method method, Object target, Object[] args) {
		try {
			method.setAccessible(true);
			return get(MemberKey.of(method, target)).asCached(method.invoke(target, args));
		} catch(InvocationTargetException e){
			try {
				return get(MemberKey.of(method, target)).asCached(e.getTargetException());
			} catch (Throwable e1) {
				Throwables.throwIfUnchecked(e);
				throw new RuntimeException(e);
			}
		} catch (IllegalAccessException | IllegalArgumentException e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		} catch (Throwable e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	/**
	 * 如果缓存中不存在指定方法对应InvokeCache对象，则通过执行反射计算创建缓存方法对应的InvokeCache
	 * 
	 * @param method 目标方法
	 * @param target 方法所属对象实例（静态方法时为null）
	 * @param args 方法调用参数
	 * @param computed 原子布尔标记，用于返回是否执行过反射计算
	 * @return 方法对应的调用缓存对象
	 */
	private InvokeCache reflectComputeIfAbsent(MemberKey memberKey, Object[] args,AtomicBoolean computed) {
		if(getIfPresent(memberKey) == null) {
	    	reflectCompute((Method) memberKey.member, memberKey.target, args);
	    	if(null != computed) {
	    		computed.set(true);
	    	}
	    }
	    try {
	    	return get(memberKey);
		} catch (Throwable e) {
			/** 抛出异常则返回 null */
			return null;
		}
	}
	/**
	 * 处理REFRESH策略的缓存更新逻辑
	 */
	private void handleRefreshStrategy(boolean computed, InvokeCache invokeCache, InvokeKey invokeKey, 
			MemberKey memberKey) {
		if (computed) {
			// 已经计算过，无需再次刷新
			return;
		}
		if (null != invokeCache.cache.getIfPresent(invokeKey.resetForNextLookup())) {
			/** 将 JoinPoint对象增加强引用，避免在执行刷新前被JVM回收 */
			ProceedingJoinPoint joinPoint = invokeKey.getJoinPoint();
			if (null != joinPoint) {
				invokeCache.refresh(invokeKey.resetForNextLookup());
				return;
			}
		}
		/** 
		 * 当JoinPoint为null或指定的key不存在时，通过反射调用缓存方法的方式强制刷新缓存，
		 * JoinPoint为null这情况只会在使用 @AoUpdateable 注解的方法
		 * 向缓存中添加新的InvokeKey上执行计算时出现，
		 * 因为此时缓存中的InvokeKey是由InvokeKey(Object target, Object[] args)构造方法构造的，
		 * 而该构造方法中JoinPoint为null，
		 * 所以此时的InvokeKey不能直接使用 computeAndCacheNoThrow 方法刷新缓存，
		 * 只能通过反射调用缓存方法的方式强制计算并刷新缓存，
		 * 调用前必须删除缓存数据。如果在有缓存数据的情况，不能真正执行计算方法
		 */
		invokeCache.remove(invokeKey);
		/** 设置刷新调用标记，指示切面调用结束时不记录日志 */
		ContextHolder.getLocalContext().setRefreshInvocation(true);
		reflectCompute((Method) memberKey.member, memberKey.target, invokeKey.args);
		if(debugOutput){
			logger.log("reflectCompute invokeKey:{}", invokeKey.toSimpleString());
		}
	}

	/**
	 * 根据指定的更新策略更新指定成员键对应的缓存。<p>
	 * 该方法会根据传入的更新策略，对指定成员键和参数对应的缓存项进行操作。<br>
	 * 支持的更新策略包括：<ul>
	 *   <li>ALWAYS - 无条件更新/添加缓存值</li>
	 *   <li>REPLACE - 仅当键存在时更新缓存值</li>
	 *   <li>REMOVE - 移除指定键的缓存值</li>
	 *   <li>REFRESH - 重新计算并更新缓存值</li>
	 * </ul><p>
	 * <p>空值校验规则：
	 * <ul>
	 *   <li>member参数非Method类型时立即返回</li>
	 *   <li>args为null时终止操作</li>
	 *   <li>updateStrategy为null时终止操作</li>
	 * </ul>
	 * <p>REFRESH策略特殊处理：
	 * <ul>
	 *   <li>首次执行时通过反射强制计算缓存值</li>
	 *   <li>处理@AoUpdateable注解触发的更新时，JoinPoint为null则执行反射计算</li>
	 *   <li>发现无效缓存条目（JoinPoint为null）时自动清除</li>
	 * </ul>
	 * 
	 * 
	 * @param invokeCache 要更新的缓存对象，可能为 null。
	 * @param computed 标识是否已经执行过计算更新缓存。
	 * @param updateStrategy 更新策略枚举，定义缓存更新方式（ALWAYS/REPLACE/REMOVE/REFRESH）。
	 * @param memberKey 包含成员信息和目标对象的成员键对象，用于定位要更新的缓存。
	 * @param args 调用成员时使用的参数数组，用于构建缓存键。为null时不执行策略更新
	 * @param value 待更新的缓存值（仅 ALWAYS/REPLACE 策略有效）。
	 */
	protected void update(InvokeCache invokeCache, boolean computed, UpdateStrategy updateStrategy, MemberKey memberKey, Object[] args, Object value,
			Object[] removeArgs) {
		/** 忽略null updateStrategy */
		if (null == updateStrategy) {
			return;
		}
		if (!(memberKey.member instanceof Method)) {
			if (debugOutput) {
				logger.log("WARNING: member is not Method type");
			}
			return;
		}
		/** 检查method对应的缓存对象是否存在,如果不存在则说明目标方法不是aocache缓存注解标记的缓存方法 */
		if (null != invokeCache) {
			if (null != removeArgs && !Arrays.deepEquals(args, removeArgs)) {
				/** 移除指定的缓存项 */
				InvokeKey removeKey = new InvokeKey(removeArgs);
				invokeCache.remove(removeKey);
				if (debugOutputDetail(invokeCache)) {
					logger.log("REMOVE cache for key: {}", removeKey);
				}
			}
			/** 忽略null args */
			if(null == args){
				return;
			}
			InvokeKey invokeKey = new InvokeKey(args);
			switch (updateStrategy) {
			case ALWAYS:
				invokeCache.put(invokeKey, value);
				break;
			case REPLACE:
				invokeCache.replace(invokeKey, value);
				break;
			case REMOVE:{
				Object old = invokeCache.remove(invokeKey);
				if (debugOutputOf(invokeCache)) {
					logger.log("{} cache for key: {},{}", updateStrategy, invokeKey.toSimpleString(), null != old);
				}
				break;
			}
			case REFRESH: {
				handleRefreshStrategy(computed, invokeCache, invokeKey, memberKey);
				break;
			}
			default:
				throw new IllegalArgumentException("Unsupported updateStrategy: " + updateStrategy);
			}
			if (updateStrategy!=UpdateStrategy.REMOVE&& debugOutputOf(invokeCache)) {
				logger.log("{} cache for key: {}", updateStrategy, invokeKey.toSimpleString());
			}
		} else if (debugOutput) {
			/** 输出警告日志：目标方法不是aocache缓存注释标记的缓存目标方法 */
			logger.log(
					"WARNING: {} is not a method targeted for caching with aocache annotations (@AoCacheable, @AoWeakCacheable)",
					memberKey.member);
		}
	}

	/**
	 * 根据指定的更新策略更新指定成员的缓存。<p>
	 * 该方法会根据传入的更新策略，对指定成员、目标对象、参数对应的缓存项进行操作。<br>
	 * 支持的更新策略包括：<ul>
	 *   <li>ALWAYS - 无条件更新/添加缓存值</li>
	 *   <li>REPLACE - 仅当键存在时更新缓存值</li>
	 *   <li>REMOVE - 移除指定键的缓存值</li>
	 *   <li>REFRESH - 重新计算并更新缓存值</li>
	 * </ul><p>
	 * 空值校验规则：<ul>
	 *   <li>若{@code updateStrategy}为{@code null}，则忽略本次操作</li>
	 *   <li>若{@code member}不是{@code Method}类型，会输出警告日志并忽略本次操作</li>
	 *   <li>若{@code args}为{@code null}，则忽略本次操作</li>
	 * </ul>
	 * 
	 * @param updateStrategy 更新策略枚举，定义缓存更新方式（ALWAYS/REPLACE/REMOVE/REFRESH）。
	 * @param member 要更新缓存的成员对象，如方法或构造函数。
	 * @param target 成员的调用对象，当成员为静态成员时，该参数可忽略。
	 * @param args 调用成员时使用的参数数组，用于构建缓存键。
	 * @param value 待更新的缓存值（仅ALWAYS/REPLACE策略有效）。
	 * @param removeArgs 需要删除的旧缓存参数。
	 * @see #update(UpdateStrategy, MemberKey, Object[], Object, Object[])
	 */
	private void update(UpdateStrategy updateStrategy, Member member, Object target, Object[] args, Object value, Object[] removeArgs) {
		if(null == member) {
			return;
		}
		MemberKey memberKey = MemberKey.of(member, target);
		/** 是否执行计算更新缓存 */
		AtomicBoolean computed = new AtomicBoolean(false);
		/** 如果缓存中不存在method对应的InvokeCache，则尝试执行反射计算更新缓存 */
		InvokeCache invokeCache = reflectComputeIfAbsent(memberKey, args, computed);
		update(invokeCache, computed.get(), updateStrategy, memberKey, args, value, removeArgs);
	}

	/**
	 * 更新缓存数据
	 * <p>
	 * 此方法是{@link #update(UpdateStrategy, Member, Object, Object[], Object, Object[])}的便捷版本，
	 * 它接受类名、方法名和参数类型来标识目标方法，而不是直接使用Member对象。
	 * 
	 * @param updateStrategy 更新策略
	 * @param clazz          目标类
	 * @param methodName     方法名称
	 * @param parameterTypes 方法参数类型数组
	 * @param target         目标对象
	 * @param args           方法参数值数组
	 * @param value          需要更新的值
	 * @param removeArgs     需要删除的旧缓存参数
	 * @throws NoSuchMethodException 当找不到匹配的方法时抛出此异常
	 * @see #update(UpdateStrategy, Member, Object, Object[], Object, Object[])
	 */
	private void update(UpdateStrategy updateStrategy, Class<?> clazz, String methodName, Class<?>[] parameterTypes,
			Object target, Object[] args, Object value, Object[] removeArgs) throws NoSuchMethodException {
		Member member = AocacheUtils.resolveAccessibleExecutableMember(clazz, methodName, parameterTypes, target, args);
		AocacheUtils.checkParameterLength(parameterTypes, args);
		AocacheUtils.checkParameterLength(parameterTypes, removeArgs);
		update(updateStrategy, member, target, args, value, removeArgs);
	}

	/**
	 * [before]更新缓存切面执行
	 * 拦截的方法执行前更新指定方法的缓存，
	 */
	public void beforeUpdate(JoinPoint joinPoint) throws NoSuchMethodException {
		if (joinPoint.getSignature() instanceof MethodSignature) {
			MethodSignature signature = (MethodSignature) joinPoint.getSignature();
			Method method = signature.getMethod();
			AoUpdateable annot = method.getAnnotation(AoUpdateable.class);
			if (annot != null) {
				Class<?> targetClass = annot.targetClass();
				/**
				 * 注解中没有指定targetClass则默认为拦截方法所属的类型
				 */
				if (targetClass.equals(Object.class)) {
					targetClass = method.getDeclaringClass();
				}
				Object[] args = joinPoint.getArgs();
				Class<?>[] parameterTypes = signature.getParameterTypes();
				String[] parameterNames = signature.getParameterNames();
				if (parameterTypes.length == 5) {
					/** 如果有5个参数，则第4，5个参数不都为Object[]，也不能都为非Object[]类型 */
					if (parameterTypes[3] == Object[].class && parameterTypes[4] == Object[].class) {
						AocacheLogger.DEFAULT.log(
								"The fourth and fifth parameters %s and %s of the method must not be Object[] at the same time",
								parameterNames[3], parameterNames[4]);
						return;
					} else if (parameterTypes[3] != Object[].class && parameterTypes[4] != Object[].class) {
						AocacheLogger.DEFAULT.log(false,
								"The fourth and fifth parameters %s and %s of the method must be not Object[] at the same time",
								parameterNames[3], parameterNames[4]);
						return;
					}
				}
				/**
				 * 方法参数为3,4或5个 则按照指定的更新策略更新缓存
				 */
				if (args.length >= 3 && args.length <= 5) {
					UpdateStrategy strategy = (UpdateStrategy) args[0];
					Object[] invokeArgs = (Object[]) args[1];
					Object value = args[2];
					Object invokeTarget = null;
					Object[] removeArgs = null;
					/** 如果存在第四个参数(可选),为Object[]类型,则为删除缓存参数，为非数组非primitive类型,则为执行目标 */
					if (args.length > 3) {
						if (parameterTypes[3] == Object[].class) {
							removeArgs = (Object[]) args[3];
						} else {
							if (parameterTypes[3].isArray() || parameterTypes[3].isPrimitive()) {
								AocacheLogger.DEFAULT.log(
										"The fourth parameter %s of the method must be not array or primitive type",
										parameterNames[3]);
								return;
							}
							invokeTarget = args[3];
						}
					}
					/**
					 * 如果存在第五个参数(可选)，为Object[]类型,则为删除缓存参数，为非数组非primitive类型,则为执行目标
					 */
					if (args.length > 4) {
						if (parameterTypes[4] == Object[].class) {
							removeArgs = (Object[]) args[4];
						} else {
							if (parameterTypes[4].isArray() || parameterTypes[4].isPrimitive()) {
								AocacheLogger.DEFAULT.log(
										"The fifth parameter %s of the method must be not array or primitive type",
										parameterNames[4]);
								return;
							}
							invokeTarget = args[4];
						}
					}
					if (invokeTarget == null) {
						invokeTarget = joinPoint.getTarget();
					}
					update(strategy, targetClass, annot.methodName(), annot.parameterTypes(), invokeTarget, invokeArgs,
							value, removeArgs);
				}
			}
		}
	}
	private boolean debugOutputOf(InvokeCache invokeCache) {
		return override ? debugOutput: invokeCache.debugOutput;
	}
	private boolean debugOutputDetail(InvokeCache invokeCache) {
		return override ? debugOutputDetail: invokeCache.debugOutputDetail;
	}
	private boolean outputAroundCost(InvokeCache invokeCache) {
		if(this.logger == AocacheLogger.MUTE) {
			return false;
		}
		return override ? outputAroundCost: invokeCache.outputAroundCost;
	}

    /**
     * [用于测试]根据给定的成员、目标对象和参数数组生成一个 InvokeKey 对象。<p>
     * 该方法用于创建一个唯一标识特定方法调用的 InvokeKey 对象，<br>
     * 该对象包含了方法调用的相关信息，如目标对象和参数列表。<p>
     * 
     * @param member 要调用的成员对象，如方法或构造函数。<p>
     * @param target 成员的调用对象，当 member 为静态成员时，该参数可忽略。<p>
     * @param args 调用成员时使用的参数数组。<p>
     * @return 一个新的 InvokeKey 对象，用于标识特定的方法调用。
     */
    InvokeKey invokeKeyOf(Member member, Object target, Object[] args) {
		InvokeCache invokeCache = getValueOrNull(MemberKey.of(member, target));
		if (null == invokeCache) {
			return null;
		}
		return FluentIterable.from(invokeCache.cache.asMap().keySet()).filter(new InvokMatcher(args)).first()
				.orNull();
	}

	InvokeKey invokeKeyOf(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object target, Object[] args)
			throws NoSuchMethodException {
		Member method = AocacheUtils.resolveAccessibleExecutableMember(clazz, methodName, parameterTypes, target, args);
		AocacheUtils.checkParameterLength(parameterTypes, args);
		return invokeKeyOf(method, target, args);
	}

	/**
	 * 尝试获取指定成员在给定目标对象和参数下的缓存值。<p>
	 * 如果缓存中存在对应的缓存项，则返回该缓存项的值；<br>
	 * 若缓存中不存在对应的缓存项，则返回 {@code null}。<p>
	 * 
	 * @param <T> 缓存值的类型。
	 * @param member 要获取缓存值的成员对象，如方法或构造函数。
	 * @param target 成员的调用对象，当成员为静态成员时，该参数可忽略。
	 * @param args 调用成员时使用的参数数组。
	 * @return 如果缓存中存在对应的值，则返回该值；否则返回 {@code null}。
	 */
	@SuppressWarnings("unchecked")
	public <T> T getCachedIfPresent(Member member, Object target, Object[] args) {
		InvokeCache invokeCache = getValueOrNull(MemberKey.of(member, target));
		if (null == invokeCache) {
			return null;
		}
		return (T) invokeCache.getValueOrNull(new InvokeKey(args));
	}
	/**
	 * 尝试获取指定类中指定方法名和参数类型的方法，在给定目标对象和参数下的缓存值。<p>
	 * 如果缓存中存在对应的缓存项，则返回该缓存项的值；<br>
	 * 若缓存中不存在对应的缓存项，则返回 {@code null}。<p>
	 * 若未找到匹配的可访问方法，将抛出NoSuchMethodException异常。<p>
	 * 
	 * @param <T> 缓存值的类型。
	 * @param clazz 要获取缓存值的方法所在的类。
	 * @param methodName 方法名。
	 * @param parameterTypes 方法的参数类型数组。
	 * @param target 方法的调用对象，当方法为静态方法时，该参数可忽略。
	 * @param args 调用方法时使用的参数数组。
	 * @return 如果缓存中存在对应的值，则返回该值；否则返回 {@code null}。
	 * @throws NoSuchMethodException 当未找到匹配的可访问方法时抛出此异常。
	 */
	public <T> T getCachedIfPresent(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object target, Object[] args) throws NoSuchMethodException {
		Member method = AocacheUtils.resolveAccessibleExecutableMember(clazz, methodName, parameterTypes, target, args);
		AocacheUtils.checkParameterLength(parameterTypes, args);
		return getCachedIfPresent(method, target, args);	
	}
	/**
	 * 返回指定成员指定参数调用的访问计数
	 * @param member 成员对象
	 * @param target 目标
	 * @param args 参数列表
	 */
	public long invokeCountOf(Member member, Object target, Object[] args) {
		try {
			InvokeCache invokeCache=  get(MemberKey.of(member, target));
			if(debugOutputOf(invokeCache) && debugOutputDetail(invokeCache)) {
				logger.log("InvokeCache {},size:{} \nFOR {}",invokeCache,invokeCache.cache.size(),member);
			}
			InvokeKey key = invokeKeyOf(member, target, args);
			if(null!= key) {
				return key.proceedCounter.get();
			}
			if(debugOutputOf(invokeCache)) {
				logger.log("NOT FOUND matched InvokeKey by target:{},args:({}) FOR\n{}",
						target,Joiner.on(",").join(args),
						member);
			}
			return 0L;
		} catch (Throwable e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * [用于测试]返回指定方法指定参数调用的访问计数
	 * @param clazz 方法所在的类
	 * @param methodName 方法名
	 * @param parameterTypes 参数类型数组,为{@code null}时，args数组不能有null元素
	 * @param target 目标对象,静态方法为{@code null}
	 * @param args 参数数组
	 * @throws NoSuchMethodException 
	 */
	public long invokeCountOf(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object target, Object[] args) throws NoSuchMethodException {
		Member method = AocacheUtils.resolveAccessibleExecutableMember(clazz, methodName, parameterTypes, target, args);
		AocacheUtils.checkParameterLength(parameterTypes, args);
		return invokeCountOf(method, target, args);
	}
	/**
	 * [用于测试]测试]返回静态方法指定参数调用的访问计数
	 * @see #invokeCountOf(Class, String, Class[], Object, Object[])
	 */
	public long invokeCountOf(Class<?> clazz, String methodName) throws NoSuchMethodException {
		return invokeCountOf(checkNotNull(clazz,"clazz is null"),methodName,null,EMPTY_CLASS_PARAMETERS,EMPTY_OBJECT_ARRAY);
	}
	/**
	 * [用于测试]测试]返回指定实例的方法的指定参数调用的访问计数
	 * @see #invokeCountOf(Class, String, Class[], Object, Object[])
	 */
	public long invokeCountOf(Object target, String methodName) throws NoSuchMethodException {
		return invokeCountOf(checkNotNull(target,"target is null").getClass(),methodName,EMPTY_CLASS_PARAMETERS,target,EMPTY_OBJECT_ARRAY);
	}
	/**
	 * [用于测试]测试]返回静态方法指定参数调用的访问计数
	 * @see #invokeCountOf(Class, String, Class[], Object, Object[])
	 */
	public long invokeCountOf(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object[] args) throws NoSuchMethodException {
		return invokeCountOf(checkNotNull(clazz,"clazz is null"),methodName,parameterTypes,null,args);
	}
	/**
	 * [用于测试]测试]返回指定实例的方法的指定参数调用的访问计数
	 * @see #invokeCountOf(Class, String, Class[], Object, Object[])
	 */
	public long invokeCountOf(Object target, String methodName, Class<?>[] parameterTypes, Object[] args) throws NoSuchMethodException {
		return invokeCountOf(checkNotNull(target,"target is null").getClass(),methodName,parameterTypes,target,args);
	}

    /**
     * 合并多个{@link com.google.common.cache.CacheStats}对象为一个。<p>
     * 如果传入的列表中只有一个元素，则直接返回该元素；<br>
     * 如果列表中有多个元素，则将第一个元素与其他元素合并，最后返回合并后的第一个元素；<br>
     * 如果列表为空，则根据emptyToNull参数决定返回值：若为true则返回null，若为false则返回一个所有统计值为0的{@link com.google.common.cache.CacheStats}对象。
     * 
     * @param stats 要合并的{@link com.google.common.cache.CacheStats}对象列表
     * @param emptyToNull 列表为空时，是否返回null。若为true，列表为空则返回null；若为false，列表为空则返回一个所有统计值为0的{@link com.google.common.cache.CacheStats}对象。
     * @return 合并后的{@link com.google.common.cache.CacheStats}对象，如果列表为空且emptyToNull为true则返回null，否则返回合并后的结果或默认的统计值为0的对象
     */
    private com.google.common.cache.CacheStats merge(List<com.google.common.cache.CacheStats> stats, boolean emptyToNull) {
		if (stats.size() > 1) {
			if (debugOutput) {
				logger.log("MERGE {} CACHE", stats.size());
			}
			for (int i = 1; i < stats.size(); i++) {
				stats.get(0).plus(stats.get(i));
			}
			return stats.get(0);
		} else if (stats.size() == 1) {
			if (debugOutput) {
				logger.log("MATCH ONE CACHE");
			}
			return stats.get(0);
		}
		return emptyToNull ? null : new com.google.common.cache.CacheStats(0L, 0L, 0L, 0L, 0L, 0L);
	}

    /**
     * [用于测试] 返回指定方法或构造器指定目标对象的访问统计信息。<p>
     * 如果成员是静态的，或者目标对象为null，则会合并所有与该成员相关的缓存统计信息。<br>
     * 若未找到对应的缓存，将返回null。<br>
	 * 如果方法或构造器为null，则返回所有缓存对象的合并统计信息。
     * 
     * @param member 方法或构造器
     * @param target 目标对象
     * @return 访问统计信息
     */
    private CacheStats statsOf(Member member, Object target) {
    	com.google.common.cache.CacheStats result = null;
		if(null == member) {
			/** 返回所有缓存对象的合并统计信息 */
			List<com.google.common.cache.CacheStats> stats = new ArrayList<>();
			for (Member m : staticMemberCache.cache.asMap().keySet().toArray(new Member[0])) {
				InvokeCache ic = staticMemberCache.getValueOrNull(m);
				if (null != ic) {
					stats.add(ic.cache.stats());
				}
			}
			for (Member m : nonStaticMemberCache.cache.asMap().keySet().toArray(new Member[0])) {
				TargetCache targetCache = nonStaticMemberCache.getValueOrNull(m);
				if (null != targetCache) {
					for (Object tgt : targetCache.cache.asMap().keySet().toArray(new Object[0])) {
						InvokeCache ic = targetCache.getValueOrNull(tgt);
						if (null != ic) {
							stats.add(ic.cache.stats());
						}
					}
				}
			}
			com.google.common.cache.CacheStats merge = merge(stats, false);
			if(null == merge) {
				if (debugOutput) {
					logger.log("NOT FOUND CACHE of ALL");
				}	
			}
			result = merge;
		}else if (Modifier.isStatic(member.getModifiers()) || null != target) {
			InvokeCache invokeCache = getValueOrNull(MemberKey.of(member, target));
			if (null != invokeCache) {
				result = invokeCache.cache.stats();
			}
		} else {
			List<com.google.common.cache.CacheStats> stats = new ArrayList<>();
			TargetCache targetCache = nonStaticMemberCache.getValueOrNull(member);
			if(null != targetCache){
				for (Object tgt : targetCache.cache.asMap().keySet().toArray(new Object[0])) {
					InvokeCache ic = targetCache.getValueOrNull(tgt);
					if (null != ic) {
						stats.add(ic.cache.stats());
					}
				}
			}
			com.google.common.cache.CacheStats merge = merge(stats, true);
			if(null == merge) {
				if (debugOutput) {
					logger.log("NOT FOUND CACHE of Member:{}", member);
				}
			}
			result = merge;
		}
		return CacheStats.of(result);
	}

    /**
     * [用于测试] 返回指定类中指定方法名和参数类型的方法，在指定目标对象下的访问统计信息。<p>
     * 如果参数类型数组为null，则使用空的参数类型数组。<br>
     * 若未找到匹配的可访问方法，将抛出NoSuchMethodException异常。<br>
	 * 如果所有参数都为null，则返回所有缓存对象的合并统计信息。
     * 
     * @param clazz 方法所在的类
     * @param methodName 方法名
     * @param parameterTypes 参数类型数组，可为null
     * @param target 目标对象，静态方法时为null
     * @return 该方法的访问统计信息
     * @throws NoSuchMethodException 当未找到匹配的可访问方法时抛出
     */
    public CacheStats statsOf(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object target)
			throws NoSuchMethodException {
		if(null == clazz && methodName == null && parameterTypes == null && target == null) {
			/** 所有参数为null，返回所有缓存对象的合并统计信息 */
			return statsOf(null, null);
		}
		Member member = AocacheUtils.resolveAccessibleExecutableMember(clazz, methodName, parameterTypes, target, null);
		return statsOf(member, target);
	}
    /**
     * [用于测试] 返回所有缓存对象的合并访问统计信息。<p>
     * 该方法会调用 {@link #statsOf(Member, Object)} 方法，传入 null 作为成员和目标对象，<br>
     * 从而获取所有缓存对象的合并统计信息。
     * 
     * @return 所有缓存对象的合并访问统计信息
     */
    public CacheStats globalStats(){
        return statsOf(null, null);
    }
    /**
     * 控制台输出指定类中指定方法名和参数类型的方法，在指定目标对象下的缓存统计信息。<p>
     * 如果参数类型数组为null，则使用空的参数类型数组。<br>
     * 若未找到匹配的可访问方法，将抛出NoSuchMethodException异常。<br>
     * 如果所有参数都为null，则输出所有缓存对象的合并统计信息。
     * 
     * @param clazz 方法所在的类
     * @param methodName 方法名
     * @param parameterTypes 参数类型数组，可为null
     * @param target 目标对象，静态方法时为null
     * @throws NoSuchMethodException 当未找到匹配的可访问方法时抛出
     */
    public void logStatsOf(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object target) throws NoSuchMethodException {
		Member member;
		if(null == clazz && methodName == null && parameterTypes == null && target == null) {
			/** 所有参数为null，返回所有缓存对象的合并统计信息 */
			member = null;
		}else{
			member = AocacheUtils.resolveAccessibleExecutableMember(clazz, methodName, parameterTypes, target, null);
		}
		CacheStats stats = statsOf(member, target);
		if (null != stats) {
			if(null == member) {
				AocacheLogger.DEFAULT.log("CACHE STATS(缓存统计) OF ALL");
			}else{
				AocacheLogger.DEFAULT.log("CACHE STATS(缓存统计) OF {} for {}:", member, target);
			}
			logStats(stats, AocacheLogger.DEFAULT);
		}else {
			logger.log("NOT FOUND STATS OF {} for {}:", member, target);
		}
	}

    /**
     * 控制台输出所有缓存对象的合并统计信息。<p>
     * 该方法会调用 {@link #logStatsOf(Class, String, Class[], Object)} 方法，传入 null 作为类、方法名、参数类型和目标对象，<br>
     * 从而输出所有缓存对象的合并统计信息。
     */
    public void logGlobalStats(){
        try {
			logStatsOf(null, null, null, null);
		} catch (NoSuchMethodException e) {
			// DO NOTHING
		}
    }
	/**
	 * 输出缓存统计信息到指定的日志记录器。
	 * <p>
	 * 该方法会将缓存统计信息（如请求总数、命中次数、命中率等）输出到指定的日志记录器。<br>
	 * 如果传入的日志记录器为null，则默认使用AocacheLogger.DEFAULT。
	 * 
	 * @param stats  缓存统计信息对象，包含了各种缓存操作的统计数据。
	 * @param logger 日志记录器，用于输出缓存统计信息。如果为null，则使用默认的日志记录器。
	 */
	public void logStats(CacheStats stats, AocacheLogger logger) {
		if (null != stats) {
			if (null == logger) {
				logger = AocacheLogger.DEFAULT;
			}
			logger.log("\t├─requestCount(请求总数):{}", stats.requestCount());
			logger.log("\t├─hitCount(命中次数):{}", stats.hitCount());
			logger.log("\t├─hitRate(命中率):{}", stats.hitRate());
			logger.log("\t├─missCount(未命中次数):{}", stats.missCount());
			logger.log("\t├─missRate(未命中率):{}", stats.missRate());
			logger.log("\t├─loadCount(加载次数):{}", stats.loadCount());
			logger.log("\t├─loadSuccessCount(加载成功次数):{}", stats.loadSuccessCount());
			logger.log("\t├─loadExceptionCount(加载异常次数):{}", stats.loadExceptionCount());
			logger.log("\t├─loadExceptionRate(加载异常率):{}", stats.loadExceptionRate());
			logger.log("\t├─totalLoadTime(总加载时间):{}", stats.totalLoadTime());
			logger.log("\t├─averageLoadPenalty(平均加载延迟):{}", stats.averageLoadPenalty());
			logger.log("\t└─evictionCount(淘汰次数):{}", stats.evictionCount());
		}
	}

	/**
	 * 输出缓存统计信息到默认的日志记录器。
	 * <p>
	 * 该方法会将缓存统计信息（如请求总数、命中次数、命中率等）输出到默认的日志记录器AocacheLogger.DEFAULT。<br>
	 * 
	 * @param stats 缓存统计信息对象，包含了各种缓存操作的统计数据。
	 */
	public void logStats(CacheStats stats) {
		logStats(stats, AocacheLogger.DEFAULT);
	}
	private static class InvokMatcher implements Predicate<InvokeKey> {
		final Object[] args;
		InvokMatcher(Object[] args) {
			this.args = args;
		}
		@Override
		public boolean apply(InvokeKey input) {
			Object[] _args = null == args ? EMPTY_OBJECT_ARRAY:args;
			return Objects.deepEquals(_args, input.args);
		}
	}
	protected Object remove(MemberKey key){
		if(key.target == null){
			return staticMemberCache.remove(key.member);
		}
		TargetCache targetCache = nonStaticMemberCache.getValueOrNull(key.member);
		return null == targetCache ? null : targetCache.remove(key.target);
	}
	private InvokeCache getIfPresent(MemberKey memberKey) {
		if(memberKey.target == null){
			return (InvokeCache) staticMemberCache.cache.getIfPresent(memberKey.member);
		}
		TargetCache targetCache = nonStaticMemberCache.getValueOrNull(memberKey.member);
		return (InvokeCache) (null == targetCache? null : targetCache.cache.getIfPresent(memberKey.target));
	}
	InvokeCache get(MemberKey memberKey) throws Throwable {
		if(memberKey.target == null){
			return staticMemberCache.get(memberKey.member);
		}
		return nonStaticMemberCache.get(memberKey.member).get(memberKey.target);
	}
	
	private InvokeCache getValueOrNull(MemberKey memberKey) {
		if(memberKey.target == null){
			return staticMemberCache.getValueOrNull(memberKey.member);
		}
		TargetCache targetCache = nonStaticMemberCache.getValueOrNull(memberKey.member);
		return targetCache == null ? null : targetCache.getValueOrNull(memberKey.target);
	}
	/**
	 * 静态成员缓存类，继承自 {@link ThrowingFunctionCached}。<p>
	 * 该类用于管理静态成员（如静态方法、构造方法）对应的缓存对象。<br>
	 */
	private class StaticMemberCache extends ThrowingFunctionCached<Member, InvokeCache>
			implements ThrowingFunction<Member, InvokeCache, Throwable>, RemovalListener<Object, InvokeCache> {

		@SuppressWarnings({ "rawtypes", "unchecked" })
		private StaticMemberCache(ThrowingFunctionCached.Builder builder) {
			super(builder.cacheBuilder);
		}

		@Override
		public InvokeCache apply(Member t) throws Throwable {
			return MemberCache.this.apply(MemberKey.of(t, null));
		}

		@Override
		public void onRemoval(RemovalNotification<Object, InvokeCache> notification) {
			notification.getValue().clear();
		}
	}
	/**
	 * 目标对象缓存类，继承自 {@link ThrowingFunctionCached}。<p>
	 * 该类用于管理特定成员在不同目标对象下的缓存。每个成员对应一个 {@link TargetCache} 实例，<br>
	 * 该实例中存储了该成员在不同目标对象下的 {@link InvokeCache} 缓存。<p>
	 */
	private class TargetCache extends ThrowingFunctionCached<Object, InvokeCache>
			implements ThrowingFunction<Object, InvokeCache, Throwable>, RemovalListener<Object, InvokeCache> {
		private Member member;

		@SuppressWarnings({ "rawtypes", "unchecked" })
		private TargetCache(Member member, ThrowingFunctionCached.Builder builder) {
			super(builder.cacheBuilder);
			this.member = checkNotNull(member, "member is null");
		}

		@Override
		public InvokeCache apply(Object target) throws Throwable {
			return MemberCache.this.apply(MemberKey.of(member, checkNotNull(target, "target is null")));
		}

		@Override
		public void onRemoval(RemovalNotification<Object, InvokeCache> notification) {
			notification.getValue().clear();
		}
	}
	/**
	 * 非静态成员缓存类，继承自 {@link ThrowingFunctionCached}。<p>
	 * 该类用于管理非静态成员的缓存，每个非静态成员对应一个 {@link TargetCache} 实例。<br>
	 */
	private class NonStaticMemberCache extends ThrowingFunctionCached<Member, TargetCache>
		implements ThrowingFunction<Member, TargetCache, Throwable>{
		
		@SuppressWarnings({ "rawtypes", "unchecked" })
		private NonStaticMemberCache(ThrowingFunctionCached.Builder builder) {
			super(builder.cacheBuilder);
		}

		@Override
		public TargetCache apply(Member member) throws Throwable {
			return new TargetCache(member,
					ThrowingFunctionCached.builder()
					/** 
					 * NOTE: 设置Key弱引用,
					 * 这里需要Key弱引用，否则会导致缓存中的没有被引用的对象一直存在，造成内存泄漏。
					 * 原因：
					 * 对于非静态方法，target为对象实例,每个实例对应一个缓存对象，
					 * 如果Key为强引用，
					 * 会导致MemberCache中的没有被外部引用的target对象对应的的缓存对象一直存在，无限增加，造成内存泄漏。
					 */
					.weakKeys());
		}
	}
}